﻿Public Module KeyboardHook

    Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Integer, ByVal lpfn As LowLevelKeyboardProcDelegate, ByVal hMod As IntPtr, ByVal dwThreadId As Integer) As IntPtr
    Declare Function UnhookWindowsHookEx Lib "user32" Alias "UnhookWindowsHookEx" (ByVal hHook As IntPtr) As Boolean
    Declare Function CallNextHookEx Lib "user32" Alias "CallNextHookEx" (ByVal hHook As IntPtr, ByVal nCode As Integer, ByVal wParam As Integer, ByRef lParam As KBDLLHOOKSTRUCT) As Integer
    Delegate Function LowLevelKeyboardProcDelegate(ByVal nCode As Integer, ByVal wParam As Integer, ByRef lParam As KBDLLHOOKSTRUCT) As Integer


    'Prevent Delegate as Global variable:
    Private ProcDelegate As LowLevelKeyboardProcDelegate

    Const WH_KEYBOARD_LL As Integer = 13

    Structure KBDLLHOOKSTRUCT
        Dim vkCode As Integer
        Dim scanCode As Integer
        Dim flags As Integer
        Dim time As Integer
        Dim dwExtraInfo As Integer
    End Structure

    Dim intLLKey As IntPtr

    Public Sub SetHook()

        'Then use the global variable to hold the new delegate preventing garbage collection
        ProcDelegate = New LowLevelKeyboardProcDelegate(AddressOf LowLevelKeyboardProc)

        'Use the delegate to set the hook
        intLLKey = SetWindowsHookEx(WH_KEYBOARD_LL, ProcDelegate, IntPtr.Zero, 0)
    End Sub

    Public Sub RemoveHook()
        UnhookWindowsHookEx(intLLKey)
    End Sub

    Private Function LowLevelKeyboardProc(ByVal nCode As Integer, ByVal wParam As Integer, ByRef lParam As KBDLLHOOKSTRUCT) As Integer
        Dim Esc As Boolean = False
        Dim Hotkey As Boolean = False

        Select Case wParam
            Case MainForm.pa
                Hotkey = ((lParam.vkCode = MainForm.code) AndAlso (lParam.flags = MainForm.flg))
                'Case 260
                'Alt-Space
                '   Hotkey = ((lParam.vkCode = 32) AndAlso (lParam.flags = 32))
            Case 256
                'Escape
                Esc = ((lParam.vkCode = 27) AndAlso (lParam.flags = 0))
        End Select

        If Hotkey = True Then
            If MainForm.Visible = False Then
                My.Computer.Keyboard.SendKeys(" ")
                MainForm.Keytxt.Text = ""
                MainForm.Show()
                MainForm.Activate()
            Else
                MainForm.Hide()
            End If
        ElseIf Esc = True Then
            MainForm.Hide()
        Else
            Return CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam)
        End If
        Return 1
    End Function
End Module